package com.github.dote.mio.util;

import lombok.val;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 反射工具类
 *
 * @author Dote
 *
 */
public class ReflectionUtil {

    //第一个数组参数
    public static final Integer ARRAY_FRIST_INDEX = 0;

    public static final String PATTERN_MAPPER = "Mapper";

    /**
     * 获取参数类型
     *
     * @param cls
     * @return
     */
    public static Class<?> getArgumentType(Class<?> cls) {
        Type[] types = ((ParameterizedType) cls.getGenericSuperclass()).getActualTypeArguments();
        return (Class<?>) types[ARRAY_FRIST_INDEX];
    }

    /**
     * 获取匹配的Mapper
     *
     * @param cls
     * @return
     */
    public static Class<?> getMatcherMapper(Class<?> cls) {
        Class<?>[] classes = cls.getInterfaces();
        Pattern pattern = Pattern.compile(getArgumentType(cls).getSimpleName() + PATTERN_MAPPER);
        for (Class<?> c : classes) {
            Matcher matcher = pattern.matcher(c.getSimpleName());
            if (matcher.find()) {
                return c;
            }
        }
        return null;
    }

    /**
     * 根据类的泛型索引获取该泛型的类型
     * @param cls
     * @param index 索引
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static Class getSuperClassGenricType(Class cls, int index) {
        Type genType = cls.getGenericSuperclass();// 得到泛型父类
        if (!(genType instanceof ParameterizedType)) {
            return Object.class;
        }
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        if (index >= params.length || index < 0) {
            throw new RuntimeException("Input Index Error");
        }
        if (!(params[index] instanceof Class)) {
            return Object.class;
        }
        return (Class) params[index];
    }

    /**
     * 获取泛型的接口
     * @param cls
     * @param impIndex
     * @param index
     * @return
     */
    public static Class getSuperInterfaceGenricType(Class cls, int impIndex,int index) {
        Type[] genTypes = cls.getGenericInterfaces();
        Type genType=null;
        if(genTypes.length>impIndex)
             genType=genTypes[impIndex];
        if (genType==null || !(genType instanceof ParameterizedType)) {
            return Object.class;
        }
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        if (index >= params.length || index < 0) {
            throw new RuntimeException("Input Index Error");
        }
        if (!(params[index] instanceof Class)) {
            return Object.class;
        }
        return (Class) params[index];
    }

}
